import styles from "./styles/global.module.css";
import nm from "nomatter";
import { countWords } from "@homegrown/word-counter";

function isPostPage(pathname: string) {
  return /\/post\/\d+(?:\/|$)/.test(pathname);
}

function isEditorPage(pathname: string) {
  return /\/editor\/drafts\/\d+(?:\/|$)/.test(pathname);
}

type ListenerType = (
  request: [input: RequestInfo, init?: RequestInit | undefined],
  resp: Response
) => void;
const fetchListeners: Record<string, ListenerType> = {};

function rewriteFetch() {
  const originFetch = unsafeWindow.fetch;
  unsafeWindow.fetch = function (...rest) {
    return originFetch.apply(this, rest).then((response) => {
      Object.values(fetchListeners).forEach((listener) =>
        listener(rest, response.clone())
      );
      return response;
    });
  };
}

function addFetchListener(id: string, listener: ListenerType) {
  fetchListeners[id] = listener;
}

function mount(selector: string): Promise<Element> {
  return new Promise((resolve) => {
    const metaBox = document.querySelector(selector);
    if (!metaBox) {
      setTimeout(() => resolve(mount(selector)), 1000);
    } else {
      resolve(metaBox);
    }
  });
}

function renderReadInfo() {
  mount(".article-area .author-info-block .meta-box").then((metaBox) => {
    const span = document.createElement("span");
    span.style.marginLeft = "0.5em";
  });
}

class ArticleRenderer {
  element: Element | null = null;
  async render(count: number) {
    if (!this.element) {
      const viewCount = await mount(
        ".article .author-info-box > .meta-box > .views-count"
      );

      if (!this.element) {
        const span = document.createElement("span");
        span.className = styles["word-count"];
        this.element = span;
        viewCount.insertAdjacentElement("afterend", this.element);
      }
    }
    this.element.textContent = `字数 ${count}`;
  }
}

class EditorRenderer {
  element: Element | null = null;
  async render(count: number) {
    if (!this.element) {
      const rightBox = await mount(
        ".markdown-editor .editor-header > .right-box"
      );

      if (!this.element) {
        const div = document.createElement("div");
        div.className = styles.status_text;
        this.element = div;
        rightBox.insertBefore(div, rightBox.children[1]);
      }
    }
    this.element.textContent = `字数：${count}`;
  }
}

function countMarkdownContent(mark_content: string) {
  return countWords(nm(mark_content).trim());
}

function render() {
  if (isPostPage(location.pathname)) {
    const renderer = new ArticleRenderer();
    addFetchListener("post", ([api], response) => {
      if (
        /https:\/\/api\.juejin\.cn\/content_api\/v1\/article\/detail/.test(
          api.toString()
        )
      ) {
        response.json().then(({ err_msg, data }) => {
          if (err_msg === "success") {
            renderer.render(
              countMarkdownContent(data.article_info.mark_content)
            );
          }
        });
      }
    });
  } else if (isEditorPage(location.pathname)) {
    const renderer = new EditorRenderer();
    addFetchListener("editor", ([api], response) => {
      const isLoaded =
        api === "https://api.juejin.cn/content_api/v1/article_draft/detail";
      const isUpdated =
        api === "https://api.juejin.cn/content_api/v1/article_draft/update";

      if (isLoaded || isUpdated) {
        response.json().then(({ err_msg, data }) => {
          if (err_msg === "success") {
            const mark_content = isLoaded
              ? data.article_draft.mark_content
              : data.mark_content;
            renderer.render(countMarkdownContent(mark_content));
          }
        });
      }
    });
  }
}

export default {
  onLoaded() {
    rewriteFetch();
    render();
  },
  onRouteChange() {
    render();
  },
};
